#include <osal/osal.h>
#include <api/libc/alloc.h>
#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <hld/hld_dev.h>
#include <sys_config.h>
#include <mediatypes.h>
#include <hld/decv/vdec_driver.h>
#include <hld/dis/VPO.h>
#include <hld/decv/decv.h>

#ifdef DUAL_ENABLE
#include <modules.h>
enum HLD_DECV_FUNC{
    FUNC_VDEC_OPEN = 0,   
    FUNC_VDEC_CLOSE,
    FUNC_VDEC_START,
    FUNC_VDEC_STOP,
    FUNC_VDEC_VBV_REQUEST,
    FUNC_VDEC_VBV_UPDATE,
    FUNC_VDEC_SET_OUTPUT,
    FUNC_VDEC_SWITCH_PIP,
    FUNC_VDEC_SWITCH_PIP_EXT,
    FUNC_VDEC_SYNC_MODE,
    FUNC_VDEC_EXTRAWIN_STORE_LAST_PIC,
    FUNC_VDEC_PROFILE_LEVEL,
    FUNC_VDEC_IO_CONTROL,
    FUNC_VDEC_PLAYMODE,
    FUNC_VDEC_DVR_SET_PARAM,
    FUNC_VDEC_DVR_PAUSE,
    FUNC_VDEC_DVR_RESUME,
    FUNC_VDEC_STEP,
    FUNC_H264_DECODER_SELECT,
    FUNC_GET_SELECTED_DECODER,
    FUNC_IS_CUR_DECODER_AVC,
    FUNC_SET_AVC_OUTPUT_MODE_CHECK_CB,
    FUNC_VIDEO_DECODER_SELECT,
    FUNC_GET_CURRENT_DECODER,
};

#ifndef _HLD_DECV_REMOTE
RET_CODE vdec_dvr_set_param(struct vdec_device *dev, struct VDec_DvrConfigParam param);
enum video_decoder_type get_current_decoder(void);
UINT32 hld_decv_entry[] = 
{
#ifdef USE_NEW_VDEC
    (UINT32)vdec_open,
    (UINT32)vdec_close,
    (UINT32)vdec_start,
    (UINT32)vdec_stop,
    (UINT32)vdec_vbv_request,
    (UINT32)vdec_vbv_update,
    (UINT32)vdec_set_output,
    (UINT32)vdec_switch_pip,
    (UINT32)vdec_switch_pip_ext,
    (UINT32)vdec_sync_mode,
    (UINT32)vdec_extrawin_store_last_pic,
#if (SYS_CHIP_MODULE == ALI_S3601 || SYS_CHIP_MODULE == ALI_S3602)
    (UINT32)vdec_profile_level,
#endif
    (UINT32)vdec_io_control,
    (UINT32)vdec_playmode,
    (UINT32)vdec_dvr_set_param,
    (UINT32)vdec_dvr_pause,
    (UINT32)vdec_dvr_resume,
    (UINT32)vdec_step,
#else
    (UINT32)vdec_open,
    (UINT32)vdec_close,
    (UINT32)vdec_start,
    (UINT32)vdec_stop,
    (UINT32)vdec_vbv_request,
    (UINT32)vdec_vbv_update,
    (UINT32)vdec_set_output,
    (UINT32)vdec_switch_pip,
    (UINT32)vdec_sync_mode,
    (UINT32)vdec_io_control,
#endif
    (UINT32)h264_decoder_select,
    (UINT32)get_selected_decoder,
    (UINT32)is_cur_decoder_avc,
    (UINT32)set_avc_output_mode_check_cb,
    (UINT32)video_decoder_select,
    (UINT32)get_current_decoder,
};    
void hld_decv_callee(UINT8 *msg)
{
    OS_hld_callee(hld_decv_entry, msg);
}
#endif

#ifdef _HLD_DECV_REMOTE
extern struct vdec_callback g_vdec_cb;
UINT32 desc_vdec_p_uint32[] = 
{ //desc of pointer para
  1, DESC_OUTPUT_STRU(0, 4),  
  1, DESC_P_PARA(0, 2, 0),
  //desc of pointer ret
  0,                          
  0,
};

UINT32 desc_vdec_get_status[] = 
{ //desc of pointer para
  1, DESC_OUTPUT_STRU(0, sizeof(struct VDec_StatusInfo)),
  1, DESC_P_PARA(0, 2, 0), 
  //desc of pointer ret
  0,                          
  0,
};

UINT32 desc_vdec_get_frm[] = 
{ //desc of pointer para
  1, DESC_OUTPUT_STRU(0, sizeof(struct vdec_io_get_frm_para)),
  1, DESC_P_PARA(0, 2, 0), 
  //desc of pointer ret
  0,                          
  0,
};

UINT32 desc_vdec_fill_frm[] = 
{ //desc of pointer para
  1, DESC_STATIC_STRU(0, sizeof(struct YCbCrColor)),
  1, DESC_P_PARA(0, 2, 0), 
  //desc of pointer ret
  0,                          
  0,
};

UINT32 desc_vdec_reg_callback[] = 
{ //desc of pointer para
  1, DESC_STATIC_STRU(0, sizeof(struct vdec_io_reg_callback_para)),
  1, DESC_P_PARA(0, 2, 0), 
  //desc of pointer ret
  0,                          
  0,
};

UINT32 desc_vdec_vbv_request[] = 
{ //desc of pointer para
  2, DESC_OUTPUT_STRU(0, 4), DESC_OUTPUT_STRU(1, 4), 
  2, DESC_P_PARA(0, 2, 0), DESC_P_PARA(1, 3, 1),
  //desc of pointer ret
  0,                          
  0,
};

UINT32 desc_vdec_set_output[] = 
{ //desc of pointer para
  3, DESC_STATIC_STRU(0, sizeof(struct VDecPIPInfo)), DESC_OUTPUT_STRU(1, sizeof(struct MPSource_CallBack)), DESC_OUTPUT_STRU(2, sizeof(struct PIPSource_CallBack)), 
  3, DESC_P_PARA(0, 2, 0), DESC_P_PARA(1, 3, 1), DESC_P_PARA(2, 4, 2),
  //desc of pointer ret
  0,                          
  0,
};
UINT32 desc_vdec_switch_pip[] = 
{ //desc of pointer para
  1, DESC_STATIC_STRU(0, sizeof(struct Position)),
  1, DESC_P_PARA(0, 1, 0), 
  //desc of pointer ret
  0,                          
  0,
};
UINT32 desc_vdec_switch_pip_ext[] = 
{ //desc of pointer para
  1, DESC_STATIC_STRU(0, sizeof(struct Rect)),
  1, DESC_P_PARA(0, 1, 0), 
  //desc of pointer ret
  0,                          
  0,
};
UINT32 desc_vdec_dvr_set_param[] = 
{ //desc of pointer para
  1, DESC_STATIC_STRU(0, sizeof(struct VDec_DvrConfigParam)),
  1, DESC_P_PARA(0, 1, 0), 
  //desc of pointer ret
  0,                          
  0,
};

UINT32 desc_vdec_set_output_rect[] = 
{ //desc of pointer para
  1, DESC_STATIC_STRU(0, sizeof(struct VDecPIPInfo)),
  1, DESC_P_PARA(0, 2, 0), 
  //desc of pointer ret
  0,                          
  0,
};

UINT32 desc_vdec_capture_display[] = 
{ //desc of pointer para
  1, DESC_OUTPUT_STRU(0, sizeof(struct vdec_picture)),
  1, DESC_P_PARA(0, 2, 0), 
  //desc of pointer ret
  0,                          
  0,
};

UINT32 desc_vdec_fill_bg_video[] = 
{ //desc of pointer para
  1, DESC_OUTPUT_STRU(0, sizeof(struct back_pip_info)),
  1, DESC_P_PARA(0, 2, 0), 
  //desc of pointer ret
  0,                          
  0,
};

UINT32 desc_vdec_get_multiview_buf[] = 
{ //desc of pointer para
  1, DESC_OUTPUT_STRU(0, sizeof(struct multiview_info)),
  1, DESC_P_PARA(0, 2, 0), 
  //desc of pointer ret
  0,                          
  0,
};

RET_CODE vdec_open(struct vdec_device *dev)
{
    jump_to_func(NULL, OS_hld_caller, dev, (HLD_DECV_MODULE<<24)|(1<<16)|FUNC_VDEC_OPEN, NULL);
}

RET_CODE vdec_close(struct vdec_device *dev)
{
    jump_to_func(NULL, OS_hld_caller, dev, (HLD_DECV_MODULE<<24)|(1<<16)|FUNC_VDEC_CLOSE, NULL);  
}
RET_CODE vdec_start(struct vdec_device *dev)
{
    jump_to_func(NULL, OS_hld_caller, dev, (HLD_DECV_MODULE<<24)|(1<<16)|FUNC_VDEC_START, NULL);
}
RET_CODE vdec_stop(struct vdec_device *dev,BOOL bclosevp,BOOL bfillblack)
{
    jump_to_func(NULL, OS_hld_caller, dev, (HLD_DECV_MODULE<<24)|(3<<16)|FUNC_VDEC_STOP, NULL);
}
RET_CODE vdec_vbv_request(void *dev, UINT32 uSizeRequested, void ** ppVData, UINT32 * puSizeGot, struct control_block * ctrl_blk)
{
    if(ctrl_blk != NULL)
    {
        //Just assume ctrl_blk should be NULL for remote call, for current remote call have bug to support NULL pointer.
        //After remote call support NULL pointer and we update desc_vdec_vbv_request for "ctrl_blk", 
        //then we can remove this ASSERT.
        //--Michael Xie 2010/2/10
        ASSERT(0);
    }
    jump_to_func(NULL, OS_hld_caller, dev, (HLD_DECV_MODULE<<24)|(5<<16)|FUNC_VDEC_VBV_REQUEST, desc_vdec_vbv_request);
}

void vdec_vbv_update(void *dev, UINT32 uDataSize)
{
    jump_to_func(NULL, OS_hld_caller, dev, (HLD_DECV_MODULE<<24)|(2<<16)|FUNC_VDEC_VBV_UPDATE, NULL);
}

RET_CODE vdec_set_output(struct vdec_device *dev, enum VDecOutputMode eMode,struct VDecPIPInfo *pInitInfo, 	struct MPSource_CallBack *pMPCallBack, struct PIPSource_CallBack *pPIPCallBack)
{
    jump_to_func(NULL, OS_hld_caller, dev, (HLD_DECV_MODULE<<24)|(5<<16)|FUNC_VDEC_SET_OUTPUT, desc_vdec_set_output);
}

RET_CODE vdec_switch_pip(struct vdec_device *dev, struct Position *pPIPPos)
{
    jump_to_func(NULL, OS_hld_caller, dev, (HLD_DECV_MODULE<<24)|(2<<16)|FUNC_VDEC_SWITCH_PIP, desc_vdec_switch_pip);
}

RET_CODE vdec_switch_pip_ext(struct vdec_device *dev, struct Rect *pPIPWin)
{
    jump_to_func(NULL, OS_hld_caller, dev, (HLD_DECV_MODULE<<24)|(2<<16)|FUNC_VDEC_SWITCH_PIP_EXT, desc_vdec_switch_pip_ext);
}

RET_CODE vdec_sync_mode(struct vdec_device *dev, UINT8 uSyncMode,UINT8 uSyncLevel)
{
    jump_to_func(NULL, OS_hld_caller, dev, (HLD_DECV_MODULE<<24)|(3<<16)|FUNC_VDEC_SYNC_MODE, NULL);
}

RET_CODE vdec_extrawin_store_last_pic(struct vdec_device *dev, struct Rect *pPIPWin)
{
    jump_to_func(NULL, OS_hld_caller, dev, (HLD_DECV_MODULE<<24)|(2<<16)|FUNC_VDEC_EXTRAWIN_STORE_LAST_PIC, desc_vdec_switch_pip_ext);
}

RET_CODE vdec_profile_level(struct vdec_device *dev, UINT8 uProfileLevel,VDEC_BEYOND_LEVEL cb_beyond_level)
{
    jump_to_func(NULL, OS_hld_caller, dev, (HLD_DECV_MODULE<<24)|(3<<16)|FUNC_VDEC_PROFILE_LEVEL, NULL);
}

RET_CODE vdec_io_control(struct vdec_device *dev, UINT32 io_code, UINT32 param)
{
    struct vdec_io_reg_callback_para *ppara;
    UINT32 *desc = NULL;
    
    switch(io_code)
    {
        case VDEC_IO_GET_STATUS:
            desc = desc_vdec_get_status;
            break;
        case VDEC_IO_GET_MODE:
            desc = desc_vdec_p_uint32;
            break;
        case VDEC_IO_GET_OUTPUT_FORMAT:
            desc = desc_vdec_p_uint32;
            break;
        case VDEC_IO_GET_FRM:
            desc = desc_vdec_get_frm;
            break;
        case VDEC_IO_SET_OUTPUT_RECT:
            desc = desc_vdec_set_output_rect;
            break;
#ifdef VDEC27_SUPPORT_RETURN_MULTI_FREEBUF
        case VDEC_IO_GET_FRM_ADVANCE://rachel:support_return_multi_freebuffer
            ASSERT(0); // This API is not supported any more for S3602F -- Michael Xie 2010/2/10
            break;			
#endif		
        case VDEC_IO_FILL_FRM:
        case VDEC_IO_FILL_FRM2:
            desc = desc_vdec_fill_frm;
            break;
	case VDEC_IO_CAPTURE_DISPLAYING_FRAME:
		desc = desc_vdec_capture_display;
		break;
        case VDEC_IO_REG_CALLBACK:
            ppara = (struct vdec_io_reg_callback_para *)(param);
            desc = desc_vdec_reg_callback;
            switch(ppara->eCBType)
            {
                case VDEC_CB_FIRST_SHOWED:
                    g_vdec_cb.pcb_first_showed = ppara->pCB;
			        break;
		        case VDEC_CB_MODE_SWITCH_OK:
			        g_vdec_cb.pcb_mode_switch_ok = ppara->pCB;
			        break;
		        case VDEC_CB_BACKWARD_RESTART_GOP: // used for advance play
			        g_vdec_cb.pcb_backward_restart_gop = ppara->pCB;
			        break;
		        case VDEC_CB_FIRST_HEAD_PARSED:
			        g_vdec_cb.pcb_first_head_parsed=ppara->pCB;
			        break;
                case VDEC_CB_MONITOR_FRAME_VBV:
			        g_vdec_cb.pcb_new_frame_coming = ppara->pCB;
			        break;
                case VDEC_CB_MONITOR_VDEC_START:
			        g_vdec_cb.pcb_vdec_start = ppara->pCB;
			        break;
                case VDEC_CB_MONITOR_VDEC_STOP:
			        g_vdec_cb.pcb_vdec_stop = ppara->pCB;
			        break;
				case VDEC_CB_MONITOR_USER_DATA_PARSED:
			        g_vdec_cb.pcb_vdec_user_data_parsed = ppara->pCB;
			        break;
		        default:
			        break;
            }
            break;
        case VDEC_IO_ADPCM_CMD:
            ASSERT(0); // This API is not supported any more for S3602F -- Michael Xie 2010/2/10
            break;
        case VDEC_IO_ABS_CMD:
			ASSERT(0); // This API is not supported any more for S3602F -- Michael Xie 2010/2/10
			break;
        case VDEC_IO_ERR_CONCEAL_CMD:
            ASSERT(0); // This API is not supported any more for S3602F -- Michael Xie 2010/2/10
            break;
        case VDEC_IO_DVIEW_CMD:
            ASSERT(0); // This API is not supported any more for S3602F -- Michael Xie 2010/2/10
            break;
        case VDEC_IO_MAF_CMD:
            ASSERT(0); // This API is not supported any more for S3602F -- Michael Xie 2010/2/10
            break;
        case VDEC_IO_FILL_BG_VIDEO:
            desc = desc_vdec_fill_bg_video;
            break;
        case VDEC_IO_GET_MULTIVIEW_BUF:
            desc = desc_vdec_get_multiview_buf;
            break;
        case VDEC_IO_WHY_IDLE:
        case VDEC_IO_GET_FREEBUF:
        case VDEC_IO_PRIORITY_STOP_SML:
        case VDEC_IO_FILLRECT_INBG:
#ifdef VDEC27_SUPPORT_COLORBAR
        case VDEC_IO_COLORBAR:  //only valid when vp had got one framebuffer from ve and vp.mp layer is opened.
#endif
        case VDEC_IO_PULLDOWN_ONOFF:

        case VDEC_IO_SWITCH:
        case VDEC_IO_DONT_RESET_SEQ_HEADER: 
        case VDEC_IO_SET_DROP_FRM:
#ifdef TSC_MONITOR			
        case VDEC_IO_DBG_START:
        case VDEC_IO_DBG_END:
#endif

        case VDEC_SET_DMA_CHANNEL:
        case VDEC_DTVCC_PARSING_ENABLE:
	 case VDEC_IO_CHANCHG_STILL_PIC:
	 case VDEC_IO_PAUSE_VIDEO:
	 case VDEC_IO_SET_DECODER_MODE:
	 case VDEC_IO_FIRST_I_FREERUN:
     case VDEC_IO_BG_FILL_BLACK:
     case VDEC_IO_SET_MULTIVIEW_WIN:
     case VDEC_IO_SLOW_PLAY_BEFORE_SYNC:
     case VDEC_IO_DONT_KEEP_PRE_FRAME:
        jump_to_func(NULL, OS_hld_caller, dev, (HLD_DECV_MODULE<<24)|(3<<16)|FUNC_VDEC_IO_CONTROL, NULL);
        return;        	     
	  };
    //jump_to_func(NULL, OS_hld_caller, dev, (HLD_DECV_MODULE<<24)|(3<<16)|FUNC_VDEC_IO_CONTROL, common_desc);
    jump_to_func(NULL, OS_hld_caller, dev, (HLD_DECV_MODULE<<24)|(3<<16)|FUNC_VDEC_IO_CONTROL, desc);
    return;
}

RET_CODE vdec_playmode(struct vdec_device *dev, enum VDecDirection direction, enum VDecSpeed speed)
{
    jump_to_func(NULL, OS_hld_caller, dev, (HLD_DECV_MODULE<<24)|(3<<16)|FUNC_VDEC_PLAYMODE, NULL);
}

RET_CODE vdec_dvr_set_param(struct vdec_device *dev, struct VDec_DvrConfigParam param)
{
    jump_to_func(NULL, OS_hld_caller, dev, (HLD_DECV_MODULE<<24)|(2<<16)|FUNC_VDEC_DVR_SET_PARAM, NULL);
}

RET_CODE vdec_dvr_pause(struct vdec_device *dev)
{
    jump_to_func(NULL, OS_hld_caller, dev, (HLD_DECV_MODULE<<24)|(1<<16)|FUNC_VDEC_DVR_PAUSE, NULL);
}
RET_CODE vdec_dvr_resume(struct vdec_device *dev)
{
    jump_to_func(NULL, OS_hld_caller, dev, (HLD_DECV_MODULE<<24)|(1<<16)|FUNC_VDEC_DVR_RESUME, NULL);
}


RET_CODE vdec_step(struct vdec_device *dev)
{
    jump_to_func(NULL, OS_hld_caller, dev, (HLD_DECV_MODULE<<24)|(1<<16)|FUNC_VDEC_STEP, NULL);
}


void h264_decoder_select(int select, BOOL in_preivew)
{
    jump_to_func(NULL, OS_hld_caller, select, (HLD_DECV_MODULE<<24)|(2<<16)|FUNC_H264_DECODER_SELECT, NULL);
}

struct vdec_device * get_selected_decoder(void)
{
    jump_to_func(NULL, OS_hld_caller, null, (HLD_DECV_MODULE<<24)|(0<<16)|FUNC_GET_SELECTED_DECODER, NULL);
}

BOOL is_cur_decoder_avc(void)
{
    jump_to_func(NULL, OS_hld_caller, null, (HLD_DECV_MODULE<<24)|(0<<16)|FUNC_IS_CUR_DECODER_AVC, NULL);
}

void set_avc_output_mode_check_cb(VDecCBFunc pCB)
{
    jump_to_func(NULL, OS_hld_caller, pCB, (HLD_DECV_MODULE<<24)|(1<<16)|FUNC_SET_AVC_OUTPUT_MODE_CHECK_CB, NULL);
}
void video_decoder_select(enum video_decoder_type select, BOOL in_preview)
{
//#ifdef SUPPORT_AVS_DECODER
    jump_to_func(NULL, OS_hld_caller, select, (HLD_DECV_MODULE<<24)|(2<<16)|FUNC_VIDEO_DECODER_SELECT, NULL);
//#endif
}
enum video_decoder_type get_current_decoder(void )
{
//#ifdef SUPPORT_AVS_DECODER
    jump_to_func(NULL, OS_hld_caller, null, (HLD_DECV_MODULE<<24)|(0<<16)|FUNC_GET_CURRENT_DECODER, NULL);
//#endif
}
#endif
#endif
